package com.easychat.mychat.common.webSocket.netty;


import com.easychat.mychat.common.entity.config.AppConfig;
import com.easychat.mychat.common.utils.StringTools;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author susu
 * @Date 2024/9/10
 */
@Slf4j
@Component
//@ChannelHandler.Sharable
public class NettyWebSocketStarter implements Runnable{

    private static EventLoopGroup bossGroup = new NioEventLoopGroup(1); //监听连接

    private static EventLoopGroup workGroup = new NioEventLoopGroup(5); //处理已建立连接的业务操作

    @Resource
    private AppConfig appConfig;
    @Resource
    private HandlerWebSocket handlerWebSocket;

    @Override
    public void run() {
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap()
                    .group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    .childHandler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            //设置重要的处理器，处理channel中的数据
                            //对http协议的支持，使用http的编码器，解码器
                            channel.pipeline().addLast(new HttpServerCodec());
                            //聚合解码 httpRequest//httpContent/lastHttpContent到fullHttpRequest
                            //保证接收的http请求的完整性
                            channel.pipeline().addLast(new HttpObjectAggregator(64 * 1024));
                            //心跳 long readerIdleTime 读超时时间 即Server端一定时间内未接收到client端消息
                            // long writerIdleTime  写超时时间  即Server端一定时间内未发送到client端消息
                            // long allIdleTime  所有类型的超时时间
                            // , TimeUnit unit
                            channel.pipeline().addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS));
                            //超时处理器
                            channel.pipeline().addLast(new HandlerHeartBeat());

                            //将http协议升级为ws协议，对websocket支持
                            channel.pipeline().addLast(new WebSocketServerProtocolHandler("/ws",null,true,64*1024,true,true,10000L));
                            channel.pipeline().addLast(handlerWebSocket);
                        }
                    });
            Integer wsPort = appConfig.getWsPort();
            String wsPortStr = System.getProperty("ws.port");
            if (!StringTools.isEmpty(wsPortStr)){
                wsPort = Integer.parseInt(wsPortStr);
            }
            ChannelFuture channelFuture = serverBootstrap.bind(wsPort).sync();
            log.info("netty服务启动成功，端口: {}",appConfig.getWsPort());
            channelFuture.channel().closeFuture().sync();

        }catch (Exception e){
            log.error("启动信息失败",e);
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
